/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-09-14 14:37:54
 * @LastEditTime: 2021-10-09 09:55:34
 * @Description:  This files is for sdmmc hardware interface implementation
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 * 1.0   Zhugengyu   2021/8/6    init
 */
#include "ft_assert.h"
#include "fsleep.h"
#include "f_sdmmc_hw.h"
#include "f_sdmmc.h"

/**
 * @name: FSdmmcReset
 * @msg: 重置SDMMC控制器
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p, sdmmc控制块
 */
u32 FSdmmcReset(FSdmmcCtrl *ctrl_p)
{
    FT_ASSERTZERONUM(ctrl_p);
    u32 ret = FSDMMC_SUCCESS;
    u32 timeout = 0;
    u32 regVal;

    FSDMMC_SET_SWR(ctrl_p, FSDMMC_SOFTWARE_RESET_SRST);
    fsleep_microsec(1);
    FSDMMC_CLR_SWR(ctrl_p, FSDMMC_SOFTWARE_RESET_SRST);

    do
    {
        regVal = FSDMMC_GET_STATUS(ctrl_p);
        fsleep_microsec(1);
    } while ((!(regVal & FSDMMC_STATUS_IDIE)) && (FSDMMC_TIMEOUT > ++timeout));

    if (FSDMMC_TIMEOUT <= timeout)
    {
        FSDMMC_ERROR("timeout when reset FSdmmc %d", ctrl_p->config.instance_id);
        ret = FSDMMC_TIMEOUT;
    }

    return ret;
}

void FSdmmcResetReadDMA(FSdmmcCtrl *ctrl_p, uintptr card_addr, u32 blk_cnt, const u8 *buf_p)
{
    FT_ASSERTVOID(ctrl_p && buf_p);

    u32 dsth = UPPER_32_BITS((uintptr)buf_p); /* DMA传输目的地址--> sd read buf */
    u32 dstl = LOWER_32_BITS((uintptr)buf_p);
    u32 srch = UPPER_32_BITS((uintptr)card_addr); /* DMA传输源地址 --> sd card */
    u32 srcl = LOWER_32_BITS((uintptr)card_addr);

    FSDMMC_INFO("sd card: 0x%x:0x%x ==> mem space: 0x%x:0x%x", 
                srch, srcl, dsth, dstl);

    FSDMMC_INFO("read %d blks from 0x%x", blk_cnt, card_addr);

    /* DMA 复位 */
    FSDMMC_SET_SWR(ctrl_p, FSDMMC_SOFTWARE_RESET_BDRST);
    FSDMMC_CLR_SWR(ctrl_p, FSDMMC_SOFTWARE_RESET_BDRST); 

    /* 设置传输块数目 */
    FSDMMC_SET_BLK_CNT(ctrl_p, blk_cnt); 

    /* 清除状态寄存器 */
    FSDMMC_CLR_BD_ISR_STATUS(ctrl_p);
    FSDMMC_CLR_NORMAL_INT_STATUS(ctrl_p);  

    FSDMMC_INFO("DMA READ START!");

    /* DMA 读卡地址配置：4 个 cycle
    系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */
    FSDMMC_SET_RX_BD(ctrl_p, dstl);
    FSDMMC_SET_RX_BD(ctrl_p, dsth);
    FSDMMC_SET_RX_BD(ctrl_p, srcl);
    FSDMMC_SET_RX_BD(ctrl_p, srch);

    return;
}

void FSdmmcResetWriteDMA(FSdmmcCtrl *ctrl_p, uintptr card_addr, u32 blk_cnt, const u8 *buf_p)
{
    FT_ASSERTVOID(ctrl_p && buf_p);
    u32 srch = UPPER_32_BITS((uintptr)buf_p);     /* DMA传输源地址--> sd read buf */
    u32 srcl = LOWER_32_BITS((uintptr)buf_p);
    u32 dsth = UPPER_32_BITS((uintptr)card_addr); /* DMA传输目的地址 --> sd card */
    u32 dstl = LOWER_32_BITS((uintptr)card_addr);

    /* DMA 复位 */
    FSDMMC_SET_SWR(ctrl_p, FSDMMC_SOFTWARE_RESET_BDRST);
    FSDMMC_CLR_SWR(ctrl_p, FSDMMC_SOFTWARE_RESET_BDRST);

    /* 设置传输块数目 */
    FSDMMC_SET_BLK_CNT(ctrl_p, blk_cnt);

    /* 清除状态寄存器 */
    FSDMMC_CLR_BD_ISR_STATUS(ctrl_p);
    FSDMMC_CLR_NORMAL_INT_STATUS(ctrl_p); 

    /* DMA 写卡地址配置：4 个 cycle
    系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */
    FSDMMC_SET_TX_BD(ctrl_p, srcl);
    FSDMMC_SET_TX_BD(ctrl_p, srch);
    FSDMMC_SET_TX_BD(ctrl_p, dstl);
    FSDMMC_SET_TX_BD(ctrl_p, dsth);

    FSDMMC_INFO("DMA WRITE START!");

    return;    
}
